#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<sys/root.h>
#include<sys/link.h>
#include <sys/thread.h>
#define BUFFER 10000
#define col 10
#define etc 5
#define rows 4


int ID;
int procN;
/LinkCB_t *LinkFo, *LinkTo;

// структура для передаваемого сообщения
struct Matrix_1
{
	double matr[col][etc]; 
};

struct Matrix_2
{
	double matr[etc][rows]; 
};

struct Matrix
{
	double matr[col][rows]; 
};

// установка линков между процессорами
int setAllLink(void)
{
	//int i; 
	//int error;
	//int id_to;
	//i = 1234;
	
	
	if (ID = 0) //первый процессор
	{
		LinkTo = MakeLink(ID+1, i, &error);
		if (LinkTo==NULL) 
		{
			LogError(EC_ERROR, "ID", "\n make link error = %d", error);
			exit(1);
		}
		LinkFo = GetLink(procN-1, i, &error);
		if (LinkFo==NULL) 
		{
			LogError(EC_ERROR, "ID", "\n Get link error = %d", error);
			exit(1);
		}
		
	}
	else //остальные процессоры
	{
		LinkFo = GetLink(ID-1, i, &error);
		if (LinkFo==NULL) 
		{
			LogError(EC_ERROR, "ID", "\nGet link error = %d", error);
			exit(1);
		}
		id_to = ID+1;	
		if (ID == procN-1) { id_to = 0; } // установка линка между последним и первый
		LinkTo = MakeLink(id_to, i, &error);
		if (LinkTo==NULL) 
		{
			LogError(EC_ERROR, "ID", "\n make link error = %d", error);
			exit(1);
		}
	}
	return 0;
}

int MatrixSumm()
{
   struct Matrix_2 AllM;
   struct Matrix_1 FirstM;
   struct Matrix Over;

   int k, i; 
	printf("First %d x %d \n", col, etc);
		
	for (k=0; k<col; k=k+1)
	{
	   for (i=0; i<etc; i=i+1)
	   {
		FirstM.matr[k][i] = random() - 30;
		printf("%d ", FirstM.matr[k][i]);
           }
	   printf("\n");
	}
	
	printf("Second %d x %d \n", etc,rows);
	for (k=0; k<etc; k=k+1)
	{
	   for (i=0; i<rows; i=i+1)
	   {
		AllM.matr[k][i] = random() - 40;
		printf("%d ", AllM.matr[k][i]);
           }
	   printf("\n");
	}



       	RecvLink (LinkFo, (byte*) &AllM, BUFFER);
      
      	SendLink (LinkTo, (byte*) &AllM, BUFFER);

      	RecvLink (LinkFo, (byte*) &FirstM, BUFFER);

        SendLink (LinkTo, (byte*) &FirstM, BUFFER);
 
      	RecvLink (LinkFo, (byte*) &Over, BUFFER);

        SendLink (LinkTo, (byte*) &Over, BUFFER);

	printf("Result %d x %d \n", col,rows);
	for (k=0; k<etc; k=k+1)
	{
	   for (i=0; i<rows; i=i+1)
	   {
		printf("%d ", Over.matr[k][i]);
           }
	   printf("\n");
	}



return 0; 
}


int SRMatrix(void)
{
   struct Matrix_2 AllM;
   struct Matrix_1 FirstM;
   struct Matrix Over;
   double matr[col][rows]; 
   double el; 
   int begin, end;
   int t, f, dx;
   int k,i,j;

      	RecvLink (LinkFo, (byte*) &AllM, BUFFER);      
      	SendLink (LinkTo, (byte*) &AllM, BUFFER);

      	RecvLink (LinkFo, (byte*) &FirstM, BUFFER);

        SendLink (LinkTo, (byte*) &FirstM, BUFFER);
      
        t = ceil(col/procN);
	f = floor(col/procN);
	fmod(col/procN,dx);

	
	if (ID<=dx)
	   {
		begin = (ID-1)*(t);
		end = begin + t; 
	   }
	else
	   {
		begin=dx+(ID-1)*f;
		end = begin+f;
	   }
		
	for (k=begin; k<end; k+1)
	{

	    for (i=0; i<rows; i=i+1)
	    {
		matr[k][i]=0;
	    }
	    for (j=0;j<etc;j+1)
		{
		    el = FirstM.matr[k][j];
		    for (i=0; i<rows; i=i+1)
			{
			   matr[k][i]=el*AllM.matr[j][i];			   
			}
		}
		
	}

      	RecvLink (LinkFo, (byte*) &Over, BUFFER);
	for (k=begin; k<end; k=k+1)
	{
	   for (i=0; i<rows; i=i+1)
	   {
		Over.matr[k][i]=matr[k][j];
           }
	}

        SendLink (LinkTo, (byte*) &Over, BUFFER);
  return 0;
}

int main(int argc, char* argv[])
{

int res;
ID = GET_ROOT()->ProcRoot->MyProcID; 
procN = GET_ROOT()->ProcRoot->nProcs;

res = setAllLink();

if (ID == 0) 
{
   MatrixSumm();

}
else
{
   SRMatrix();
}

return 0;

}
